﻿namespace IBTrader.Model
{
    using IBTrader.Frontend;
    using IBTrader.Modules.Configuration;
    using IBTrader.Modules.Read;
    using IBTrader.Properties;
    using NLog;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Xml.Serialization;

    public class BacklogConfigurations : List<BacklogConfiguration>
    {
    }
    public class BacklogConfiguration : NotifyPropertyChanged, IStoreMember, IReaderConfiguration
    {
        private static readonly Logger logger = LogManager.GetCurrentClassLogger();
        public BacklogConfiguration() { }
        public BacklogConfiguration(Store store)
        {
            this.Store = store; 
            this.Id = store.BacklogConfigurations.Count + 1;
            this.Folder = Settings.Default.BacklogFolder;
            this.FileFormat = "{0} {1:" + Times.DateFormat + "}.{2}";
        }
        private DateTime date;
        private string fileFormat;

        public int Id { get; set; }
        public string Folder { get; set; }
        public string FileFormat { get { return fileFormat; } set { fileFormat = value; Changed(() => FileFormat); } }
        public DateTime Date { get { return date; } set { date = value; Changed(() => Date); } }

        [XmlIgnore]
        public Store Store { get; set; }
        [XmlIgnore]
        public Algo Algo { get { return Store.Algos.Single(a => a.BacklogConfigurationId == Id); } }
        [XmlIgnore]
        public TimeSpan From { get { return Algo.TradingStart; } }
        [XmlIgnore]
        public TimeSpan To { get { return Algo.TradingEnd; } }

        public FileInfo BinaryFile()
        {
            return FileInfo("bin");
        }
        public FileInfo TextFile()
        {
            return FileInfo("txt");
        }
        private FileInfo FileInfo(string extension, DateTime? dt = null)
        {
            return new FileInfo(Path.Combine(Folder, string.Format(FileFormat, Algo.Contract.Symbol, dt??Date, extension)));
        }
        private IEnumerable<string> Symbols()
        {
            return Directory.GetFiles(Folder).Select(f => new FileInfo(f).Name).Select(n => n.Split(' ').First()).Distinct().OrderBy(n => n);
        }
        private static IEnumerable<DateTime> Days() 
        { 
            for (var dt = new DateTime(2011, 1, 1); dt <= DateTime.Today; dt = dt.AddDays(1)) yield return dt; 
        }
        private IEnumerable<DateTime> Dates()
        {
            return Days().Where(dt => FileInfo("txt", dt).Exists);
        }
        internal bool ChangeSymbol(int offset)
        {
            return Change<string>(offset, Symbols(), () => Algo.Contract.Symbol, i => Algo.Contract.Symbol = i);
        }
        internal bool ChangeDate(int offset)
        {
            return Change<DateTime>(offset, Dates(), () => Date, i => Date = i);
        }
        private static bool Change<T>(int offset, IEnumerable<T> items, Func<T> get, Action<T> set)
        {
            try
            {
                var list = items.ToList();
                if (!list.Any()) return false;
                var index = list.IndexOf(get());
                var nextIndex = (index + list.Count + offset) % list.Count;
                set(list[nextIndex]);
                return true;
            }
            catch (Exception ex)
            {
                logger.Error(ex.Message);
                logger.Debug(ex.StackTrace);
                return false;
            }
        }

        public IEnumerable<FileFormatType> FileFormats
        {
            get
            {
                return new[] { 
                    new FileFormatType{Text="Daily Ticks", Value="{0} {1:"+Times.DateFormat+"}.{2}", Type = typeof(IBTrader.Modules.Read.ReaderDailyTickData)},
                    new FileFormatType{Text="Historical 1 Second", Value="{0} {1:"+Times.DateFormat+"} 1 secs.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 5 Seconds", Value="{0} {1:"+Times.DateFormat+"} 5 secs.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 15 Seconds", Value="{0} {1:"+Times.DateFormat+"} 15 secs.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 30 Seconds", Value="{0} {1:"+Times.DateFormat+"} 30 secs.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 1 Minute", Value="{0} {1:"+Times.DateFormat+"} 1 min.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 2 Minutes", Value="{0} {1:"+Times.DateFormat+"} 2 min.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 5 Minutes", Value="{0} {1:"+Times.DateFormat+"} 5 min.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 15 Minutes", Value="{0} {1:"+Times.DateFormat+"} 15 min.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 30 Minutes", Value="{0} {1:"+Times.DateFormat+"} 30 min.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 1 Hour", Value="{0} {1:"+Times.DateFormat+"} 1 hour.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                    new FileFormatType{Text="Historical 1 Day", Value="{0} {1:"+Times.DateFormat+"} 1 day.{2}", Type = typeof(IBTrader.Modules.Read.ReaderHistoricalData)},
                };
            }
        }
        public class FileFormatType
        {
            public string Text { get; set; }
            public string Value { get; set; }
            public Type Type { get; set; }
        }
    }
}